#pragma once
#include "stdafx.h"
#include "OgreEntity.h"
#include "Trigger.h"
#include "IParameterChangedListener.h"
#include "IntEntityParameter.h"
#include "VectorEntityParameter.h"
#include "CustomEntityParameter.h"
#include "EntityBody.h"
#include "StackAllocator.h"
#include "StackAllocatorManager.h"
#include "IStackAllocator.h"
#include "Controller.h"

class ControlContext;
class Controller;
class ControlLogic;
class PhysicsEntity;
class Trigger;

class _OgreMoveExport EntityControl :
	public Ogre::ManualObject
{
	

	//PhysicsEntity* bulletActor;
	//Ogre::Entity* modelEntity;

	//bool actorInited;

	int HitPoint;

	//std::vector<Trigger*> TriggerList;
	//std::map<std::string, EntityParameter*> parameterMap;
	//std::map<std::string, std::vector<IParameterChangedListener*>*> listenerMap;
	//std::vector<Trigger*> dirtyTriggers;
	//std::vector<Trigger*> newDirtyTriggers;

	EntityBody * masterBody;

	std::vector<EntityBody*> bodies;


protected:

	std::vector<Trigger*> TriggerList;
	std::map<std::string, std::vector<IParameterChangedListener*>*> listenerMap;
	std::map<std::string, EntityParameter*> parameterMap;
	std::vector<Trigger*> dirtyTriggers;
	void setupParameters();

	std::vector<Controller*> controllers;


	std::vector<Trigger*> newDirtyTriggers;

	
	virtual std::vector<Trigger*> getDirtyTriggerList();
	virtual std::vector<Trigger*> getNewDirtyTriggerList();
	virtual std::map<std::string, std::vector<IParameterChangedListener*>*> getListenerMap();

public:

	virtual std::vector<Trigger*> getTriggerList();

	enum EntityState{WAITING,PLAYING,DEAD,GAMEOVER,REMOVED}entityState;

	bool actorInited;

	/*static const std::string POSITION_PARAMETER;
	static const std::string HITPOINT_PARAMETER;
	static const std::string KILLED_PARAMETER;
	static const std::string SPEED_PARAMETER;
	static const std::string LOOKAT_PARAMETER;
	static const std::string MAP_WAYPOINT_PARAMETER;
	static const std::string SCORE_PARAMETER;*/

	//EntityControl(void);
	//EntityControl(const Ogre::Entity&, float hp=100);
	EntityControl(int hp=50);
	EntityControl(const Ogre::String entityName, int hp=50);

	void addController(ControlLogic*);
	virtual bool control(Controller *controller, const ControlContext&);
	
	virtual std::vector<Controller*> * getControllers();


	/// Renders the entity as seen from a given camera in a given role.
	//void render(const RenderContext& context);
	/// Updates time-varying entity properties.
	//void animate(double dt);

	virtual ~EntityControl(void);

	/*virtual PhysicsEntity* getPhysicsActor();
	virtual Ogre::Entity* getModelActor();
	virtual void setPhysicsActor(PhysicsEntity*);
	virtual void setModelActor(Ogre::Entity*);
	virtual bool isActorInited();*/

	virtual void setMasterBody(EntityBody * body);
	virtual EntityBody *  getMasterBody();
	virtual void addBody(EntityBody * body);
	virtual void removeBody(EntityBody * body);
	virtual std::vector<EntityBody*>* getBodies();
	virtual void deleteBodies();
	

	virtual void setPosition(Ogre::Vector3 pos);
	virtual void setLocalPosition(Ogre::Vector3 pos);
	virtual Ogre::Vector3 getLocalPosition();
	virtual void setLookAt(Ogre::Vector3 pos);
	virtual void setOrientation(Ogre::Quaternion ori);
	virtual Ogre::Quaternion getOrientation();
	virtual void setLocalOrientation(Ogre::Quaternion ori);
	virtual Ogre::Quaternion getLocalOrientation();
	virtual void addForce(Ogre::Vector3 force);
	virtual void addTorque(Ogre::Vector3 torque);
	virtual void killEntity();
	virtual void setEntityState(EntityState state);


	virtual void AddTrigger(Trigger *trigger);

	

	virtual Ogre::Vector3 getPosition();

	virtual void clear(void);

	virtual void setParameter(std::string name,EntityParameter *param);
	virtual EntityParameter* getParameter(std::string name);
	virtual void setTriggerDirty(Trigger *trigger);
	virtual void subscribeForParameter(std::string name,IParameterChangedListener *listener);
	virtual void unSubscribeForParameter(std::string name,IParameterChangedListener *listener);
	virtual bool isParameterFilled(std::string name);
	
	
	

	//Lowers the hitpoints with the given damage and kills himself if hitpoints go under 0
	virtual void causeDamage(float fmg);


	void kill();
	void play();
	void wait();
	void DDDIIIE();
	void GameOverMan();

	bool isPlaying();
	bool isKilled();
	bool isGameOver();
	bool isWaiting();
	bool isReadyToDie();

	

	static void* operator new (size_t size);
	static void operator delete (void *p);


};
